package com.cloudbroker.bcs.platform.ltb.middle.aspect;

import com.cloudbroker.bcs.common.annotation.NoTenant;
import com.cloudbroker.bcs.common.constants.LogFields;
import com.cloudbroker.bcs.common.context.DataContext;
import com.cloudbroker.bcs.common.util.PrintUtil;
import com.cloudbroker.bcs.common.util.VOUtil;
import com.cloudbroker.bcs.common.vo.HSBCSVOBase;
import com.cloudbroker.bcs.platform.ltb.bizapi.constants.HSBCPSErrorCodes;
import com.cloudbroker.bcs.platform.ltb.common.config.ConfigValues;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.lang.reflect.Method;
import java.util.Map;

public class DataBindAspect {
    
    private static final String CLASS_NAME = DataBindAspect.class.getName();
    
    private static final Logger LOGGER = LoggerFactory.getLogger(CLASS_NAME);
    
    public DataBindAspect() {
        PrintUtil.printComponentLoaded(LOGGER, CLASS_NAME);
    }
    
    public Object bindData(ProceedingJoinPoint pjp) throws Throwable {
        // 在Spring的环境里，signature就是MethodSignature
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        // 获取Method
        Method method = methodSignature.getMethod();
        // 方法上没有申明@NoTenant且类上也没有申明@NoTenant，则绑定租户ID
        if (!method.isAnnotationPresent(NoTenant.class)
                && !method.getDeclaringClass().isAnnotationPresent(NoTenant.class)) {
            for (Object arg : pjp.getArgs()) {
                if (arg instanceof HSBCSVOBase) {
                    Map<String, Object> result = bindTenantId((HSBCSVOBase) arg);
                    if (null != result) {
                        return result;
                    }
                } else {
                    // impossible
                    throw new RuntimeException("invalid access");
                }
            }
            
            Object result = null;
            try {
                result = pjp.proceed();
            } finally {
                clearBinding();
            }
            return result;
        } else {
            // 执行业务
            return pjp.proceed();
        }
    }
    
    private Map<String, Object> bindTenantId(HSBCSVOBase vo) {
        String tenantId = vo.getTenant_id();
        if (null == tenantId || ConfigValues.TENANT_ID_WIDTH != tenantId.length()) {
            return VOUtil.genErrorResult(HSBCPSErrorCodes.ILLEGAL_ACCESS, "tenantId", tenantId);
        }
        DataContext.setTenantId(tenantId);
        MDC.put(LogFields.TENENT_ID, tenantId);
        // 注意，这里没做clear
        // 当前是放在com.cloudbroker.bcs.common.aspect.LogAspect.log(ProceedingJoinPoint)中clear
        return null;
    }
    
    private void clearBinding() {
        DataContext.removeTenantId();
    }
    
}
